package com.sparkseries.service.impl;

import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.sparkseries.common.security.domain.SecurityUser;
import com.sparkseries.common.util.domain.Result;
import com.sparkseries.common.util.exception.BusinessException;
import com.sparkseries.common.util.tool.ObjectConvertTool;
import com.sparkseries.dao.SysCompanyMapper;
import com.sparkseries.dao.SysUserMapper;
import com.sparkseries.domain.SysCompany;
import com.sparkseries.domain.SysDepartment;
import com.sparkseries.domain.SysUser;
import com.sparkseries.domain.vo.SysDepartmentVO;
import com.sparkseries.domain.vo.SysCompanyVO;
import com.sparkseries.domain.vo.SysUserVO;
import com.sparkseries.dto.SysCompanyDTO;
import com.sparkseries.enums.DefaultStatusEnum;
import com.sparkseries.service.SysCompanyService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 企业管理
 */
@Service
@Slf4j
public class SysCompanyServiceImpl implements SysCompanyService {

    @Resource
    private SysCompanyMapper sysCompanyMapper;
    @Resource
    private SysUserMapper sysUserMapper;

    /**
     * 创建企业
     * TODO 通知管理，创建企业给管理员发送通知
     *
     * @param sysCompanyDTO 企业传输类
     * @return 默认响应类
     */
    @Override
    public Result<?> createCompany(SysCompanyDTO sysCompanyDTO) {
        // 校验企业传输类是否为null
        validateCompanyDTO(sysCompanyDTO);
        // 校验企业名是否已存在
        validUniqueCompanyName(sysCompanyDTO);
        // 校验管理员信息是否存在
        validateAdmin(sysCompanyDTO.getCompanyAdmin());
        // 校验上级企业是否为自身或者为下级企业
        validateParentId(sysCompanyDTO);

        // 企业传输类转换为企业实体类
        SysCompany sysCompany = convertToSysCompany(sysCompanyDTO);

        // 使用IdWorker工具类生成一个随机的id存入企业类
        sysCompany.setId(IdWorker.getId());
        //TODO 创建时间
        sysCompany.setCreateDate(new Date());

        // 获取所有的上级id并存入企业类
        List<Long> allParentId = getAllParentId(sysCompany);
        String parentIds = allParentId.toString();
        sysCompany.setParentIds(parentIds.substring(1, parentIds.length() - 1));

        if (sysCompanyMapper.createCompany(sysCompany) <= 0) {
            log.error("创建企业失败，企业信息: {}", sysCompanyDTO);
            throw new BusinessException("创建企业时发生异常");
        }

        log.info("创建企业成功，企业ID: {}", sysCompany.getId());
        return Result.ok("创建企业成功");
    }

    /**
     * 逻辑删除企业
     *
     * @param companyId 企业id
     * @return 默认响应类
     */
    @Override
    public Result<?> deleteCompany(Long companyId) {
        // 判断是否有子企业
        if (getAllSubId(companyId).size() > 1) {
            log.warn("该企业下有子企业解除绑定，删除企业失败，企业ID:{}", companyId);
            throw new BusinessException("该企业下有子企业解除绑定，删除企业失败");
        }

        // 判断是否有下属部门
        if (!sysCompanyMapper.listDepartmentIdByCompanyId(companyId).isEmpty()) {
            log.warn("该企业下有部门未删除，删除企业失败，企业ID:{}", companyId);
            throw new BusinessException("该企业下有部门未删除，删除企业失败");
        }

        if (sysCompanyMapper.deleteCompany(companyId) <= 0) {
            log.error("删除企业时发生异常，企业ID:{}", companyId);
            throw new BusinessException("删除企业时发生异常");
        }

        log.info("删除企业成功，企业ID: {}", companyId);
        return Result.ok("删除企业成功");
    }

    /**
     * 修改企业
     *
     * @param sysCompanyDTO 企业传输类
     * @return 默认响应类
     */
    @Override
    public Result<?> updateCompany(SysCompanyDTO sysCompanyDTO) {
        // 校验企业传输类是否为null
        validateCompanyDTO(sysCompanyDTO);
        // 校验企业名是否已存在
        validUniqueCompanyName(sysCompanyDTO);
        // 校验上级企业是否为自身或者为下级企业
        validateParentId(sysCompanyDTO);

        SysCompany sysCompany = convertToSysCompany(sysCompanyDTO);
        //TODO 修改时间
        sysCompany.setUpdateDate(new Date());

        if (sysCompanyMapper.updateCompany(sysCompany) <= 0) {
            log.error("修改企业时发生异常，企业信息:{}", sysCompanyDTO);
            throw new BusinessException("修改企业时发生异常");
        }

        log.info("修改企业成功，企业ID: {}", sysCompany.getId());
        return Result.ok("修改企业成功");
    }

    /**
     * 修改企业状态
     *
     * @param companyId 企业id
     * @param status    状态     0: 失效 1: 激活
     * @return 默认响应类
     */
    @Override
    public Result<?> updateStatus(Long companyId, Integer status) {
        if (sysCompanyMapper.updateStatus(companyId, status) <= 0) {
            log.error("修改企业状态时发生异常，企业ID:{}，企业状态:{}", companyId, status);
            throw new BusinessException("修改企业状态时发生异常");
        }

        log.info("修改企业状态成功，企业ID:{}，企业状态:{}", companyId, DefaultStatusEnum.getDesc(status));
        return Result.ok("修改企业状态成功");
    }

    /**
     * 获取企业信息
     *
     * @param companyId 企业id
     * @return 企业响应类
     */
    @Override
    public Result<SysCompanyVO> getCompanyById(Long companyId) {
        return Optional.ofNullable(sysCompanyMapper.getCompanyById(companyId))
                .map(company -> {
                    log.debug("成功获取企业信息，企业ID: {}", companyId);
                    return Result.ok("查询成功", ObjectConvertTool.originConvert(company, SysCompanyVO.class));
                })
                .orElseGet(() -> {
                    log.warn("未查询到该企业，企业ID: {}", companyId);
                    return Result.error("企业信息未找到");
                });
    }

    /**
     * 企业列表
     * TODO 普通用户只能查询自身及以下企业
     *
     * @param sysCompanyDTO 企业传输类
     * @param detail        查找关键词
     * @return 企业响应类的集合
     */
    @Override
    public Result<List<SysCompanyVO>> listCompany(SysCompanyDTO sysCompanyDTO, String detail) {
        SysCompany sysCompany = convertToSysCompany(sysCompanyDTO);

        //TODO 获取当前登录用户
        SecurityUser currentUser = (SecurityUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        List<Long> allSubId = getAllSubId(currentUser.getCompanyId());

        List<SysCompany> sysCompanies = sysCompanyMapper.listCompany(sysCompany, detail, allSubId);
        if (sysCompanies.isEmpty()) {
            log.warn("未查找到相关企业");
            return Result.error("未查找到相关企业");
        }

        List<SysCompanyVO> sysCompanyVOS = ObjectConvertTool.originsConvert(sysCompanies, SysCompanyVO.class);
        return Result.ok("查找企业列表成功", sysCompanyVOS);
    }

    /**
     * 获取企业管理员信息
     *
     * @param companyId 企业id
     * @return 用户响应类
     */
    @Override
    public Result<SysUserVO> getCompanyAdmin(Long companyId) {
        SysCompany sysCompany = sysCompanyMapper.getCompanyById(companyId);
        if (Objects.isNull(sysCompany)) {
            log.error("未查找到相关企业，企业ID:{}", companyId);
            throw new BusinessException("未查找到相关企业");
        }

        String username = sysCompany.getCompanyAdmin();

        // 校验管理员信息是否存在
        validateAdmin(username);
        SysUser sysUser = sysUserMapper.getUserByUsername(username);
        SysUserVO sysUserVO = ObjectConvertTool.originConvert(sysUser, SysUserVO.class);
        return Result.ok("企业管理员信息查找成功", sysUserVO);
    }

    /**
     * 企业添加部门
     *
     * @param departmentIds 部门id数组
     * @param companyId     企业id
     * @return 默认响应类
     */
    @Override
    public Result<?> insertDepartments(Long[] departmentIds, Long companyId) {
        // 校验部门是否唯一
        validUniqueDepartment(departmentIds, companyId);

        for (Long departmentId : departmentIds) {
            if (sysCompanyMapper.insertDepartments(departmentId, companyId) <= 0) {
                log.error("企业添加部门时发生异常，企业ID:{}，部门ID:{}", companyId, departmentId);
                throw new BusinessException("企业添加部门时发生异常");
            }
        }

        return Result.ok("添加部门成功");
    }

    /**
     * 企业删除部门
     *
     * @param departmentIds 部门id数组
     * @param companyId     企业id
     * @return 默认响应类
     */
    @Override
    public Result<?> deleteDepartments(Long[] departmentIds, Long companyId) {
        if (sysCompanyMapper.deleteDepartments(departmentIds, companyId) <= 0) {
            log.error("企业删除部门时发生异常，企业ID:{}，部门ID:{}", companyId, Arrays.toString(departmentIds));
            throw new BusinessException("企业删除部门时发生异常");
        }

        return Result.ok("删除部门成功");
    }

    /**
     * 查找某企业下的所有部门
     *
     * @param companyId 用于查找的企业id
     * @return 部门响应类的集合
     */
    @Override
    public Result<List<SysDepartmentVO>> listDepartmentByCompanyId(Long companyId) {
        List<SysDepartment> sysDepartments = sysCompanyMapper.listDepartmentIdByCompanyId(companyId);
        if (sysDepartments.isEmpty()) {
            log.warn("企业麾下暂无部门，企业ID:{}", companyId);
            return Result.error("企业麾下暂无部门");
        }

        List<SysDepartmentVO> sysDepartmentVOS = ObjectConvertTool.originsConvert(sysDepartments, SysDepartmentVO.class);

        return Result.ok("查找部门成功", sysDepartmentVOS);
    }

    //------------------------ 参数校验 ------------------------
    private void validateCompanyDTO(SysCompanyDTO dto) {
        if (Objects.isNull(dto)) {
            log.error("企业信息不能为空");
            throw new BusinessException("企业信息不能为空");
        }
    }

    // 校验管理员信息是否存在
    private void validateAdmin(String username) {
        if (Objects.isNull(sysUserMapper.getUserByUsername(username))) {
            log.error("未查找到企业管理员信息，管理员名:{}", username);
            throw new BusinessException("未找到管理员信息");
        }
    }

    //校验企业名是否唯一
    private void validUniqueCompanyName(SysCompanyDTO dto) {
        SysCompany sysCompany = sysCompanyMapper.getCompanyByCompanyName(dto.getCompanyName());

        if (!Objects.isNull(sysCompany)) {
            log.error("企业名:{}", dto.getCompanyName() + "，已存在");
            throw new BusinessException("企业名已存在");
        }
    }

    // 校验上级企业是否为自身或者为下级企业
    private void validateParentId(SysCompanyDTO dto) {
        if (!Objects.isNull(dto.getId()) && dto.getId().equals(dto.getParentId())) {
            log.error("上级企业不能为自身,企业信息:{}", dto);
            throw new BusinessException("上级企业不能为自身");
        }

        List<Long> allSubId = getAllSubId(dto.getId());
        if (allSubId.contains(dto.getParentId())) {
            log.error("上级企业不能为下级企业,企业信息:{}", dto);
            throw new BusinessException("上级企业不能为下级企业");
        }
    }

    // 校验部门是否唯一
    private void validUniqueDepartment(Long[] departmentIds, Long companyId) {
        List<Long> rDepartmentIds = sysCompanyMapper.getCompanyIdByDepartmentIds(departmentIds, companyId);

        if (!rDepartmentIds.isEmpty()) {
            for (Long rDepartmentId : rDepartmentIds) {
                log.error("部门id:{}", rDepartmentId + "，已添加");
            }
            throw new BusinessException("有部门已添加");
        }
    }

    //------------------------ 工具方法  ------------------------
    // 获取所有上级id
    private List<Long> getAllParentId(SysCompany sysCompany) {
        List<SysCompany> sysCompanies = sysCompanyMapper.listCompanyIdAndParentId();
        Map<Long, Long> map = new HashMap<>(sysCompanies.size());
        for (SysCompany company : sysCompanies) {
            map.put(company.getId(), company.getParentId());
        }
        List<Long> parentIds = new ArrayList<>();
        Long parentId = sysCompany.getParentId();
        while (!Objects.isNull(parentId)) {
            parentIds.add(parentId);
            parentId = map.get(parentId);
        }
        return parentIds;
    }

    // 获取所有下级id
    private List<Long> getAllSubId(Long companyId) {
        List<Long> subIds = sysCompanyMapper.listSubId("%" + companyId + "%");
        subIds.add(companyId);
        return subIds;
    }

    // 将 DTO 转换为实体
    private SysCompany convertToSysCompany(SysCompanyDTO dto) {
        return ObjectConvertTool.originConvert(dto, SysCompany.class);
    }

}